<?php

if (!defined('BASEPATH'))
     exit('No direct script access allowed');

class Tanya extends CI_Controller {

     function __construct() {
          parent:: __construct();
          $this->load->model('tanya_model');
          $this->load->model('tfidf_model');
          $this->load->library('kelas_pemisahan');
          $this->load->library('enhanced_cs');
          $this->load->library('call_matrix');
     }

     function cek_validasi() {
          /*
            perhatikan bagian set_rules('nama', 'nama pengguna', 'required') [contoh]
            'nama' merepresentasikan nama form input, ingat...form input
            'nama pengguna' adalah kalimat yang akan keluar bila tidak sesuai dengan validasi
            'required' maksudnya adalah form input nama wajib diisi
           */
          $this->form_validation->set_rules('judul', 'judul topik', 'required');
          $this->form_validation->set_rules('deskripsi', 'deskripsi topik', 'required');

          $this->form_validation->set_message('required', 'kolom %s harus diisi!!!');

          return $this->form_validation->run();
     }

     function form_tanya() {
          $span = "span8";
          $judul = array('name' => 'judul', 'class' => $span, 'placeholder' => 'Judul Topik...');
          $deskripsi = array('name' => 'deskripsi', 'class' => 'deskripsi');
          $tanya = array('judul' => $judul, 'deskripsi' => $deskripsi);
          return $tanya;
     }

     public function index() {
          $this->load->view('halaman_tanya', $this->form_tanya());
     }

     public function pemisahan() {
          if ($this->cek_validasi()) {

               /* ambil data dari field tanya_view, kemudian dimasukkan ke dalam
                * array bernama $data
                * data tokenizing
                * */
               $data = array
                   (
                   'kasus' => $this->input->post('deskripsi'),
                   'judul_kasus' => $this->input->post('judul'),
                   'jawaban_kasus' => "kasus belum terjawab"
               );
               $judul = $data['judul_kasus'];
               $data_deskripsi = $data['kasus'];
               $tokenizing = $this->kelas_pemisahan->tokenizing($data_deskripsi);
               $i = 0;
               //$data_stemming = implode(" ", $data_stem);
               $data_stoplist = $this->tanya_model->get_stopwords()->row()->stopwords;
               $data_filtering = $this->kelas_pemisahan->filtering($tokenizing, $data_stoplist);
               foreach ($data_filtering as $kata) {
                    $data_stem[$i] = $this->enhanced_cs->enhanced_cs2($kata);
                    $i++;
               }
               $jawaban = $this->hitung_tfidf_lsa($data_stem);
//               if ($jawaban[0] < 0.8) {
               $metode = $this->tanya_model->get_stopwords()->row()->default_method;;
               if ($metode == "lsa") {
                    $datax = array(
                        'cosine_arr_max' => $jawaban[2],
                        'cosine_arr_next' => $jawaban[3]
                    );
               } else {
                    $datax = array(
                        'cosine_arr_max' => $jawaban[0],
                        'cosine_arr_next' => $jawaban[1]
                    );
               }
               $datax['judul']=$judul;
               $datax['data_deskripsi']=$data_deskripsi;
               $datax['array_token']=$jawaban[4];
               $this->load->view('halaman_jawaban', $datax);
//               } else {
//                    echo "simpan";
//                    $this->tanya_model->insert_unique_data_kasus($data);
//               }
          } else {
               $this->index();
          }
     }

     /** Untuk menambahkan modul penambah filter
      * 1. memanggil fungsi filter(), kemudian datanya ditampilkan pada textarea filter_view (sukses)
      * 2. tambahkan kata-kata filter pada textarea. submit pada kelas control filter_update()
      * 3. Data dilempar dan disimpan pada fungsi update() pada kelas tanya_model
      * */
     public function filter() {
          $data['data_filter'] = $this->tanya_model->get_stopwords()->row()->stopwords;
          $data['default_method'] = $this->tanya_model->get_stopwords()->row()->default_method;
          $this->load->view('filter_view', $data);
     }

     public function filter_update() {
          $stopwords = $this->input->post('stopwords');
          $default_method = $this->input->post('default_method');
          if ($this->tanya_model->get_stopwords()->row()->stopwords != $stopwords ||
                  $this->tanya_model->get_stopwords()->row()->default_method != $default_method
                  ) {
               $data['stopwords'] = $stopwords;
               $data['default_method'] = $this->input->post('default_method');
               $this->tanya_model->update($data);
               $this->index();
          } else {
               echo "data yang anda masukkan sama";
          }
     }

     function array_kata($pilih) {
          $this->load->library('kelas_pemisahan');
          $data = $this->tfidf_model->data_kasus("result")->result();
          $i = 1;

          $kalimat[0] = "";
          foreach ($data as $row) {
               $kalimat[$i] = $row->kasus;
               $kalimat[$i] = $kalimat[$i - 1] . " " . $kalimat[$i];
               $i++;
          }
          $j = 0;

          foreach ($data as $row) {
               $kalimat2[$j] = $row->kasus;
               $j++;
          }
          //hahah
          $k = 0;
          foreach ($kalimat2 as $row) {
               $kata_per_kalimat[$k] = $this->kelas_pemisahan->tokenizing($row);
               $k++;
          }

          $kata_berimbuhan = $this->kelas_pemisahan->tokenizing($kalimat[$i - 1]);
          $stoplist = $this->tanya_model->get_stopwords()->row()->stopwords;
          $i = 0;
          foreach ($kata_berimbuhan as $kata) {
               //echo $kata;
               $data_stem[$i] = $this->enhanced_cs->enhanced_cs2($kata);
               $i++;
          }

          $data_filter = $this->kelas_pemisahan->filtering($data_stem, $stoplist);
          if ($pilih == "unfilter_token") {
               return $data;
          }
          $l = 0;
          foreach ($kata_per_kalimat as $row) {
               $data_filter2[$l] = $this->kelas_pemisahan->filtering($kata_per_kalimat[$l], $stoplist);
               foreach ($data_filter2 as $cols) {
                    $data_filter3[$l] = $cols;
               }
               $l++;
          }

          $unique_data_filter = array_unique($data_filter);

          $a = 0;
          //"kata_" dimulai dari 1
          foreach ($unique_data_filter as $row) {
               $kata2[$a] = $row;
               $a++;
          }

          for ($m = 1; $m < count($kata2); $m++) {
               for ($n = 0; $n < count($data_filter3); $n++) {
                    $posisisi[$m][$n] = count(array_keys($data_filter3[$n], $kata2[$m]));
               }
          }
          if ($pilih == "posisi_token") {
               return $posisisi;
          } else if ($pilih == 'array_token') {
               unset($kata2["kata_0"]);
               return $kata2;
          } else if ($pilih == 'count_document') {
               return $this->tfidf_model->data_kasus("count");
          } else if ($pilih == 'count_row_token') {
               return count($kata2);
          } else {
               echo "<h2>Wrong Parameter!!</h2> " .
               "<br><b>parameter jumlah dokumen:</b> count_document. " .
               "<br><b>parameter jumlah row kata:</b> count_row_token. " .
               "<br><b>parameter array kata:</b> array_token" .
               "<br><br>ex: array_kata('count_document')";
          }
     }

     /*
      * W(d,t)=TF(d,t)*IDF(t)
      * d = dokumen ke-d
      * t = kata ke-t dari kata kunci
      * W = bobot dokumen ke-d terhadap kata kunci ke-t
      * -------------
      * Jumlah dokumen = D
      */

     public function hitung_tfidf_lsa($kata_kunci) {
          //jumlah dokumen
          $D = $this->array_kata('count_document');

          //array token
          $array_token = $this->array_kata('array_token');

          $a = 0;
          foreach ($array_token as $row) {
               $jumlah_kata_kunci[$a] = count(array_keys($kata_kunci, $row));
               $a++;
          }
          unset($jumlah_kata_kunci[0]);

          /*
           * TF*IDF
           */
          $tf = $this->array_kata("posisi_token");
          $dokumen_frekuensi = $this->hitung_df($tf);
          $dokumen_w_tfidf = $this->hitung_tfidf($D, $tf, $dokumen_frekuensi, $jumlah_kata_kunci);
          $normal_w_doc = $this->normalisasi_dokumen($dokumen_w_tfidf['w_doc']);
          $normal_w_key = $this->normalisasi_kata_kunci($dokumen_w_tfidf['w_key']);
          $cosine_tfidf = $this->cosine_tfidf($normal_w_doc, $normal_w_key);
          $cosine_tfidf_arr_max = $this->jawab_terakurat($cosine_tfidf);
          $cosine_lsa = $this->cosine_lsa($tf, $jumlah_kata_kunci);
          $cosine_lsa_arr_max = $this->jawab_terakurat($cosine_lsa);
          $cosine_tfidf_arr_next = $this->cos_index_selanjutnya($cosine_tfidf);
          $cosine_lsa_arr_next = $this->cos_index_selanjutnya($cosine_lsa);

          $data = array(
              0 => $cosine_tfidf_arr_max,
              1 => $cosine_tfidf_arr_next,
              2 => $cosine_lsa_arr_max,
              3 => $cosine_lsa_arr_next,
              4 => $array_token,
          );

          return $data;
     }

     function transpose_array($array) {
          $output_transpose = array();
          foreach ($array as $key => $subarr) {
               foreach ($subarr as $subkey => $subvalue) {
                    $output_transpose[$subkey][$key] = $subvalue;
               }
          }
          return $output_transpose;
     }

     function table_show($value) {
          echo "<table>";
          foreach ($value as $row) {
               echo "<tr>\n";
               foreach ($row as $col) {
                    echo "<td>";
                    echo $col;
                    echo "</td>\n";
               }
               echo "</tr>\n";
          }
          echo "</table>";
     }

     /*
      * fungsi ini bertugas untuk proses perkalian dua matrix
      */

     function perkalian_matrix($M1, $M2) {

          $M2t = $this->transpose_array($M2);
          foreach ($M2t as $row => $tmp) {

               foreach ($M1 as $row1 => $tmp1) {
                    $multiply[$row1] = $this->array_rproduct($tmp, $tmp1);
                    if (!$multiply[$row1]) {
                         exit;
                    }
               }
               foreach ($multiply as $row1 => $vals) {
                    $sum[$row][$row1] = array_sum($vals);
               }
          }

          $r = $this->transpose_array($sum);
          return ($r);
     }

     function array_rproduct($a1, $a2) {

          foreach ($a1 as $line => $cols) {
               $a3[$line] = $a1[$line] * $a2[$line];
               foreach ($a2 as $line2 => $cols2) {
                    $a3[$line2] = $a1[$line2] * $a2[$line2];
               }
          }
          ksort($a3);
          return ($a3);
     }

     function count_where($input = 1, $operator = '==', $where = 1) {
          $input = is_array($input) ? $input : (array) $input;
          $operator = !in_array($operator, array('<', '>', '<=', '>=', '==', '!=')) ? '==' : $operator;

          $i = 0;

          foreach ($input as $current) {
               $match = null;
               eval('$match = (bool)("' . $current . '"' . $operator . '"' . $where . '");');

               $i = $match ? $i + 1 : $i;
          }

          return $i;
     }

     function hitung_df($value) {
          for ($a = 1; $a <= count($value); $a++) {
               $testing[$a] = $this->count_where($value[$a], '!=', 0);
          }
          return $testing;
     }

     function hitung_tfidf($D, $tf, $dokumen_frekuensi, $jumlah_kata_kunci) {
          for ($a = 1; $a <= count($tf); $a++) {
               $count_dokumen[$a] = ($dokumen_frekuensi[$a] != 0) ? (log10($D / $dokumen_frekuensi[$a])) : 0;
               //bobot kata kunci
               $idf_kata_kunci[$a] = $jumlah_kata_kunci[$a] * $count_dokumen[$a];
               for ($b = 0; $b < $D; $b++) {
                    //bobot dokumen
                    $dokumen_w_tfidf[$a][$b] = $tf[$a][$b] * $count_dokumen[$a];
               }
          }
          $data = array(
              'w_key' => $idf_kata_kunci,
              'w_doc' => $dokumen_w_tfidf
          );
          return $data;
     }

     function normalisasi_dokumen($value) {
          $a = 1;
          foreach ($value as $row) {
               $b = 0;
               foreach ($row as $cols) {
                    $w_doc[$a][$b] = $cols;
                    $b++;
               }
               $a++;
          }
          //kuadratkan bobot dokumen tfidf
          for ($a = 1; $a <= count($w_doc); $a++) {
               for ($b = 0; $b < count($w_doc[$a]); $b++) {
                    $w_doc_2[$a][$b] = $w_doc[$a][$b] * $w_doc[$a][$b];
               }
          }
          //transpose tabel bobot tfidf kuadrat
          $w_doc_2_t = $this->transpose_array($w_doc_2);

          //jumlah dan diakar bobot TF-IDF di tiap dokumen
          for ($a = 0; $a < count($w_doc_2_t); $a++) {
               $w_doc_2_t_sum_sqrt[$a] = sqrt(array_sum($w_doc_2_t[$a]));
          }
//
          //bobot normalisasi dokumen
          for ($a = 1; $a <= count($w_doc); $a++) {
               for ($b = 0; $b < count($w_doc[$a]); $b++) {
                    $w_doc_n[$a][$b] = $w_doc[$a][$b] / $w_doc_2_t_sum_sqrt[$b];
               }
          }
          return $w_doc_n;
     }

     function normalisasi_kata_kunci($value) {
          $a = 1;
          foreach ($value as $row) {
               $w_key[$a] = $row;
               $a++;
          }
          //bobot kata kunci kuadrat
          for ($a = 1; $a <= count($w_key); $a++) {
               $w_key_2[$a] = $w_key[$a] * $w_key[$a];
          }
          //jumlah, dikuadratkan, lalu diakar bobot kata kuncinya
          $w_key_2_sum_sqrt = sqrt(array_sum($w_key_2));
          //normalisasi kata kunci
          for ($a = 1; $a <= count($w_key); $a++) {
               $w_key_n[$a] = ($w_key[$a] != 0) ? ($w_key[$a] / $w_key_2_sum_sqrt) : 0;
          }
          return $w_key_n;
     }

     function cosine_tfidf($normal_w_doc, $normal_w_key) {
          //normalisasi kata kunci dikalikan normalisasi dokumen
          for ($a = 1; $a <= count($normal_w_doc); $a++) {
               for ($b = 0; $b < count($normal_w_doc[$a]); $b++) {
                    $normal_d_k[$a][$b] = $normal_w_doc[$a][$b] * $normal_w_key[$a];
               }
          }
          //transpose nor kunci dokumen
          $normal_d_k_t = $this->transpose_array($normal_d_k);
          //sum perkalian kata kunci dan dokumen
          for ($a = 0; $a < count($normal_w_doc[1]); $a++) {
               $normal_d_k_t_sum[$a] = array_sum($normal_d_k_t[$a]);
          }
          //normalisasi kata kunci dikuadratkan
          for ($a = 1; $a <= count($normal_w_key); $a++) {
               $normal_w_key_2[$a] = $normal_w_key[$a] * $normal_w_key[$a];
          }
          //normalisasi kata kunci yang dikuadratkan kemudian diakar (nanti akan dikalikan dengan hasil akar kuadrat normalisasi dari tiap dokumen
          $normal_w_key_2_sum_sqrt = sqrt(array_sum($normal_w_key_2));
          //menguadratkan masing2 kata normalisasi di tiap dokumen
          for ($a = 1; $a <= count($normal_w_doc); $a++) {
               for ($b = 0; $b < count($normal_w_doc[1]); $b++) {
                    $normal_w_doc_2[$a][$b] = $normal_w_doc[$a][$b] * $normal_w_doc[$a][$b];
               }
          }
          //transpose normalisasi yang telah dikuadratkan
          $normal_w_doc_2_t = $this->transpose_array($normal_w_doc_2);
          //menjumlahkan, kemudian mengakar hasil kuadrat masing2 kata normalisasi di tiap dokumen (dokumen 0, 1, 2, dst...)
          for ($a = 0; $a < count($normal_w_doc[1]); $a++) {
               $normal_w_doc_2_t_sum_sqrt[$a] = array_sum($normal_w_doc_2_t[$a]);
          }
          //hasil similaritas
          for ($a = 0; $a < count($normal_w_doc[1]); $a++) {
               $cosine[$a] = ($normal_d_k_t_sum[$a] != 0) ? ($normal_d_k_t_sum[$a] / ($normal_w_key_2_sum_sqrt * $normal_w_doc_2_t_sum_sqrt[$a])) : 0;
          }
          return $cosine;
     }

     function rename_array_key_cosine($cosine) {
          $kasus = $this->tanya_model->get_kasus()->result();
          //rename key array cosine similaritas
          $a = 0;
          foreach ($kasus as $row) {
               $cosine2[$row->id_data_kasus] = $cosine[$a];
               $a++;
          }
          return $cosine2;
     }

     function jawab_terakurat($cosine) {
          $cosine2 = $this->rename_array_key_cosine($cosine);
          //id similar termirip
          $max_sim = max($cosine2);
          $similar_m_id = array_search($max_sim, $cosine2);
          $judul_sim = $this->tanya_model->get_jawaban_kasus($similar_m_id)->judul_kasus;
          $kasus_sim = $this->tanya_model->get_jawaban_kasus($similar_m_id)->kasus;
          $jawab_sim = $this->tanya_model->get_jawaban_kasus($similar_m_id)->jawaban_kasus;
          $data = array
              (
              'judul_sim' => $judul_sim,
              'kasus_sim' => $kasus_sim,
              'jawab_sim' => $jawab_sim,
              'max_sim' => (round($max_sim, 4) * 100) . " %"
          );
          return $data;
     }

     function set_svd($tf, $k=null) {
          //mengambil nilai singular value dari bobot
          $S = $this->call_matrix->nilai_svd_s($tf, $k);
          //---S^-1 (Inverse Singular Value)---
          $S_inv = $this->call_matrix->inverse_array($S);
          //---U (Eigen Vektor Kiri)---
          $U = $this->call_matrix->nilai_svd_u($tf, $k);
          //---V (Eigen Vektor Kanan)---
          $V = $this->call_matrix->nilai_svd_v($tf, $k);
          $data = array
              (
              'S' => $S,
              'S_inv' => $S_inv,
              'U' => $U,
              'V' => $V
          );
          return $data;
     }

     function  cosine_lsa($tf, $jumlah_kata_kunci) {
          $k = null;
          $get_svd = $this->set_svd($tf, $k);
          //---q (Query/kata kunci)---
          for ($a = 1; $a <= count($jumlah_kata_kunci); $a++) {
               $q_key[$a - 1][0] = $jumlah_kata_kunci[$a];
          }
          //---q^T (Transpose Query/kata kunci)---
          $q_key_t = $this->transpose_array($q_key);
          //---q = q^T*U*S^-1---
          $q_key_t_u = $this->perkalian_matrix($q_key_t, $get_svd['U']);
          $q_key_t_u_s_inv = $this->perkalian_matrix($q_key_t_u, $get_svd['S_inv']);
          //q*d
          for ($a = 0; $a < count($get_svd['V']); $a++) {
               for ($b = 0; $b < count($get_svd['V'][0]); $b++) {
                    $q_key_d[$a][$b] = $get_svd['V'][$a][$b] * $q_key_t_u_s_inv[0][$b];
               }
          }
          //sum q*d dimana d adalah eigenvektor kanan
          for ($a = 0; $a < count($q_key_d); $a++) {
               $q_key_d_sum[$a] = array_sum($q_key_d[$a]);
          }
          //q^2
          //kuadrat query dokumen
          for ($a = 0; $a < count($q_key_t_u_s_inv[0]); $a++) {
               $q_key_t_u_s_inv_2[0][$a] = $q_key_t_u_s_inv[0][$a] * $q_key_t_u_s_inv[0][$a];
          }
          //sum sqrt q^2
          $q_key_t_u_s_inv_2_sum_sqrt = sqrt(array_sum($q_key_t_u_s_inv_2[0]));
          //d kuadrat
          for ($a = 0; $a < count($get_svd['V']); $a++) {
               for ($b = 0; $b < count($get_svd['V'][0]); $b++) {
                    $V_2[$a][$b] = $get_svd['V'][$a][$b] * $get_svd['V'][$a][$b];
               }
          }
          //d kuadrat dijumlah dan diakar
          for ($a = 0; $a < count($V_2); $a++) {
               $V_2_sum_sqrt[$a] = sqrt(array_sum($V_2[$a]));
          }
          //cosine similaritas lsa tiap dokumen
          for ($a = 0; $a < count($q_key_d_sum); $a++) {
               $cosine_lsa[$a] = $q_key_d_sum[$a] / ($q_key_t_u_s_inv_2_sum_sqrt * $V_2_sum_sqrt[$a]);
          }
          return $cosine_lsa;
     }

     function cos_index_selanjutnya($cosine) {
          asort($cosine, SORT_NUMERIC);
          $a = count($cosine) - 1;
          foreach ($cosine as $row) {
               $cosine_2[$a] = $row;
               $a--;
          }
          $cosine_id_key = $this->rename_array_key_cosine($cosine_2);
          $a = 0;
          foreach ($cosine_id_key as $row) {
               $id_kasus[$a] = array_search($row, $cosine_id_key);
               $similaritas[$a] = $cosine_2[$a];
               $a++;
          }
          for ($a = 0; $a < count($id_kasus); $a++) {
               $similar_judul_data[$a] = $this->tanya_model->get_jawaban_kasus($id_kasus[$a])->judul_kasus;
          }
          for ($a = 0; $a < count($id_kasus); $a++) {
               $similar_kasus_data[$a] = $this->tanya_model->get_jawaban_kasus($id_kasus[$a])->kasus;
          }
          for ($a = 0; $a < count($id_kasus); $a++) {
               $similar_jawab_data[$a] = $this->tanya_model->get_jawaban_kasus($id_kasus[$a])->jawaban_kasus;
          }
          for ($a = 1; $a < count($id_kasus); $a++) {
               $data[$a][0] = $a + 1;
               $data[$a][1] = $similar_judul_data[$a];
               $data[$a][2] = "" . (round($similaritas[$a], 4) * 100) . " %";
               $data[$a][3] = $similar_jawab_data[$a];
               $data[$a][4] = $similar_kasus_data[$a];
          }
          return $data;
     }

}